package com.office.automate.leave.data.validator;

import java.util.Date;

import com.office.automate.dataaccess.impl.administration.PublicHolidayDaoImplementer;
import com.office.automate.dataaccess.impl.leave.EmployeeLeaveDaoImplementer;
import com.office.automate.dataaccess.impl.user.EmployeeDaoImplementer;
import com.office.automate.exception.framework.FrontierVisibleException;
import com.office.automate.exception.leave.EmployeeLeaveExceptionKeys;
import com.office.automate.frontier.utility.DataConversionUtility;
import com.office.automate.model.employee.EmployeeAttandanceCommit;
import com.office.automate.model.leave.EmployeeLeave;
import com.office.automate.model.leave.LeaveRequest;
import com.office.automate.model.leave.LieuLeaveRequest;
import com.office.automate.validation.framework.BaseValidator;

public class LeaveRequestDataValidator extends BaseValidator {
	private DataConversionUtility dtUtility = new DataConversionUtility();

	/**
	 * Validate the leave request details accordingly.
	 * 
	 * @param aLeaveRequest
	 * @throws FrontierVisibleException
	 */
	public void validateLeaveRequestDetails(LeaveRequest aLeaveRequest) throws FrontierVisibleException {

		validateLeaveTypeandAvailability(aLeaveRequest);

		validateToDateAndLeaveRange(aLeaveRequest.getFromDate(), aLeaveRequest.getToDate());

		validateReason(aLeaveRequest.getReason());
	}

	private void validateLeaveTypeandAvailability(LeaveRequest aLeaveRequest) throws FrontierVisibleException {
		EmployeeLeave employeeLeave = new EmployeeLeaveDaoImplementer().getCurrentEntitlementBalance(aLeaveRequest.getFinancialYear(), aLeaveRequest.getEmployeeId());
		String leaveType = aLeaveRequest.getLeaveType();
		if (!aLeaveRequest.getFromDate().equals(new Date(0)) && 
						!aLeaveRequest.getToDate().equals(new Date(0)) && (
								aLeaveRequest.getFromDate().equals(aLeaveRequest.getToDate()) ||
								aLeaveRequest.getFromDate().before(aLeaveRequest.getToDate()))) {

			int workingDaysCount = dtUtility.getWorkingDaysCountForGivenDateRange(aLeaveRequest.getFromDate(), aLeaveRequest.getToDate()) - 
										new PublicHolidayDaoImplementer().getAvailablePublicHolidayRecordCountForDateRange(aLeaveRequest.getFromDate(), aLeaveRequest.getToDate());
			aLeaveRequest.setNumberOfDays(workingDaysCount);
			if (workingDaysCount <= 0) {
				addFieldValidationException("FromDate", new FrontierVisibleException(EmployeeLeaveExceptionKeys.NO_WORKING_DAY_FOUND_FOR_GIVEN_RANGE, null));
			}
			if (leaveType.equals("Annual") && (employeeLeave.getAnualLeaveCount() < 1 || 
						employeeLeave.getAnualLeaveCount() < workingDaysCount)) {
				addFieldValidationException("LeaveType", new FrontierVisibleException(EmployeeLeaveExceptionKeys.ANNUAL_LEAVE_COUNT_IS_NOT_ENOUGH, null));
			} else if (leaveType.equals("Casual") && workingDaysCount > 2 ) {
				addFieldValidationException("LeaveType", new FrontierVisibleException(EmployeeLeaveExceptionKeys.CASUAL_LEAVE_COUNT_IS_NOT_ENOUGH, null));
			} else if (leaveType.equals("Casual") && (employeeLeave.getCasualLeaveCount() < 1 || employeeLeave.getCasualLeaveCount() < workingDaysCount)) {
				addFieldValidationException("LeaveType", new FrontierVisibleException(EmployeeLeaveExceptionKeys.MAXIMUM_CASUAL_LEAVE_COUNT_IS_EXCEED, null));
			} else if (leaveType.equals("Medical") && (employeeLeave.getMedicalLeaveCount() < 1 || employeeLeave.getMedicalLeaveCount() < workingDaysCount)) {
				addFieldValidationException("LeaveType", new FrontierVisibleException(EmployeeLeaveExceptionKeys.MEDICAL_LEAVE_COUNT_IS_NOT_ENOUGH, null));
			} else if (leaveType.equals("Lieu") && (employeeLeave.getLieuLeaveCount() < 1 || employeeLeave.getLieuLeaveCount() < workingDaysCount)) {
				addFieldValidationException("LeaveType", new FrontierVisibleException(EmployeeLeaveExceptionKeys.LIEU_LEAVE_COUNT_IS_NOT_ENOUGH, null));
			} else if (leaveType.equals("MatOrPat") && (employeeLeave.getMaternityOrPaternityLeaveCount() < 1 || employeeLeave.getMaternityOrPaternityLeaveCount() < workingDaysCount)) {
				addFieldValidationException("LeaveType", new FrontierVisibleException(EmployeeLeaveExceptionKeys.MAT_PAT_LEAVE_COUNT_IS_NOT_ENOUGH, null));
			}			
		}
	}

	private void validateToDateAndLeaveRange(Date aFromDate, Date aToDate) {
		if (aToDate.equals(new Date(0))) {
			addFieldValidationException("ToDate", new FrontierVisibleException(EmployeeLeaveExceptionKeys.TO_DATE_IS_INVALID, null));
		}
		if (aFromDate.equals(new Date(0))) {
			addFieldValidationException("FromDate", new FrontierVisibleException(EmployeeLeaveExceptionKeys.FROM_DATE_IS_INVALID, null));
		} else if (!aFromDate.equals(aToDate) && !aFromDate.before(aToDate)) {
			addFieldValidationException("FromDate", new FrontierVisibleException(EmployeeLeaveExceptionKeys.FROM_DATE_SHOULD_EARLIER_THAN_TO_DATE, null));
		} else if (aFromDate.before(dtUtility.getBillingDateOfPreviousMonth())) {
			addFieldValidationException("FromDate", new FrontierVisibleException(EmployeeLeaveExceptionKeys.FROM_DATE_SHOULD_BE_IN_CURRENT_PAYMENT_CYCLE, null));
		}
	}

	private void validateReason(String aReason) {
		if (aReason == null || aReason.isEmpty()) {
			addFieldValidationException("Reason", new FrontierVisibleException(EmployeeLeaveExceptionKeys.REASON_IS_EMPTY, null));
		}
	}

	public void validateLieuLeaveRequestDetails(LieuLeaveRequest aLieuLeaveRequest) {
		try {
			EmployeeAttandanceCommit anEmployeeAttandanceCommit = new EmployeeDaoImplementer().getAttandanceDetails(aLieuLeaveRequest);
			if (anEmployeeAttandanceCommit == null) {
				addFieldValidationException("LieuLeaveDate", new FrontierVisibleException(EmployeeLeaveExceptionKeys.NO_ATTENDANCE_RECORD_FOUND, null));
			}
		} catch (FrontierVisibleException e) {
			addFieldValidationException("LieuLeaveDate", new FrontierVisibleException(EmployeeLeaveExceptionKeys.NO_ATTENDANCE_RECORD_FOUND, null));
		}
	}
}
